#include <Windows.h>
// #include <WinSock2.h>
// #include <ws2def.h>
// #include <ws2ipdef.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <conio.h>
#include <locale.h>

LPSTR w2u8(LPCWSTR s)
{
    int len = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL);
    LPSTR res = (LPSTR)malloc(len);
    WideCharToMultiByte(CP_UTF8, 0, s, -1, res, len, NULL, NULL);
    return res;
}

void print_bytes(FILE *f, const unsigned char*bytes, size_t len)
{
    for(size_t i = 0; i < len; i++)
        fprintf(f, !i + " %02X", bytes[i]);
}

void dump_info(PMIB_IFTABLE pIfTable);

int main()
{
    DWORD last_all_in = 0;
    DWORD last_all_out = 0;
    DWORD last_tick = 0;
        
    while(_kbhit()) _getch();
    while(!_kbhit())
    {
        ULONG ulSize = 0;
        GetIfTable(NULL, &ulSize, FALSE);
        PMIB_IFTABLE pIfTable = (PMIB_IFTABLE)malloc(ulSize);
        if(pIfTable)
        {
            if(!GetIfTable(pIfTable, &ulSize, FALSE))
            {
                PMIB_IFROW pTable = pIfTable->table + pIfTable->dwNumEntries;

                DWORD all_in = 0;
                DWORD all_out = 0;
                DWORD tick = GetTickCount();
                while(pTable-- != pIfTable->table)
                {
                    all_in += pTable->dwInOctets;
                    all_out += pTable->dwOutOctets;
                }

                if(last_tick)
                {
                    DWORD deltaIn = all_in - last_all_in;
                    DWORD deltaOut = all_out - last_all_out;
                    double deltaTick = tick - last_tick;
                    printf("\033[2K\rin: %g, out: %g", deltaIn / deltaTick, deltaOut / deltaTick);
                }

                last_all_in = all_in;
                last_all_out = all_out;
                last_tick = tick;
            }
            free(pIfTable);
        }
        Sleep(1000);
    }
    while(_kbhit()) _getch();
    return 0;
}

void dump_info(PMIB_IFTABLE pIfTable)
{
    PMIB_IFROW pTable = pIfTable->table + pIfTable->dwNumEntries;
    size_t i = 0;
    FILE *f = fopen("Z:\\net.csv", "w");
    fputs(",wszName,dwIndex,dwMtu,dwSpeed,PhysAddr,dwAdminStatus,dwOperStatus,dwLastChange,dwInOctets,dwInUcastPkts,dwInNUcastPkts,dwInDiscards,dwInErrors,dwInUnknownProtos,dwOutOctets,dwOutUcastPkts,dwOutNUcastPkts,dwOutDiscards,dwOutErrors,dwOutQLen,dwDescrLen,bDescr\n", f);
    while( pTable-- != pIfTable->table)
    {
        if(!pTable->dwPhysAddrLen || pTable->dwType != IF_TYPE_ETHERNET_CSMACD || !pTable->dwAdminStatus)
            continue;
        LPSTR name = w2u8(pTable->wszName);
        fprintf(f,"%zu,%s,%lu,%lu,%lu,",++i,name,pTable->dwIndex,pTable->dwMtu,pTable->dwSpeed);
        print_bytes(f, pTable->bPhysAddr, pTable->dwPhysAddrLen);
        fprintf(f, "%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%s\n", pTable->dwAdminStatus, pTable->dwOperStatus, pTable->dwLastChange, pTable->dwInOctets, pTable->dwInUcastPkts, pTable->dwInNUcastPkts, pTable->dwInDiscards, pTable->dwInErrors, pTable->dwInUnknownProtos, pTable->dwOutOctets, pTable->dwOutUcastPkts, pTable->dwOutNUcastPkts, pTable->dwOutDiscards, pTable->dwOutErrors, pTable->dwOutQLen, pTable->dwDescrLen, (LPCSTR)pTable->bDescr);
    }
    fclose(f);
}